package com.jackstraw.jack_base.mq.common.aspect.aop;


import com.jackstraw.jack_base.mq.common.aspect.annotation.ServerNameCut;
import com.jackstraw.jack_base.mq.common.aspect.contextholder.MqContextHolder;
import com.jackstraw.jack_base.util.StringUtil;
import com.jackstraw.jack_base.util.AspectUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * ServerName切面类
 */
@Slf4j
@Aspect
@Component
public class ServerNameAspect implements Ordered {

    @Autowired
    private StandardEnvironment environment;

    /**
     * 切入点
     */
    @Pointcut("@within(com.jackstraw.jack_base.mq.common.aspect.annotation.ServerNameCut)"
            + "&& execution(* com.jackstraw..*.mq..producer..*.*(..)))")
    public void defaultPointCut() {

    }

    @Around("defaultPointCut()")
    public Object dbDefaultCutByAround(ProceedingJoinPoint joinPoint) {
        long currentTimeMillis = System.currentTimeMillis();
        //获取Method
        Method method = AspectUtil.getMethod(joinPoint);
        // 获得目标方法名
        String methodName = method.getName();
        //获取代理的对象
        Class aClass = AspectUtil.getClass(method);
        String className = aClass.getName();
        if (StringUtil.StringUtilsBylang3.isEmpty(className) || StringUtil.StringUtilsBylang3.isEmpty(methodName)) {
            log.error("MQ获取ServerName切面异常，无法获取切面类名称或切面方法名称");
            throw new IllegalStateException("DataBase切面异常，无法获取切面类名称或切面方法名称");
        }
        log.info("AOP环绕通知【时间戳为:{}】=========={}#{}方法执行开始", currentTimeMillis, className, methodName);

        if (aClass.isAnnotationPresent(ServerNameCut.class)) {
            ServerNameCut serverNameCut = (ServerNameCut) aClass.getAnnotation(ServerNameCut.class);
            String serverName = serverNameCut.serverName();
            /**
             * 获取配置文件内容
             */
            serverName = this.environment.resolvePlaceholders(serverName);
            MqContextHolder.setServerName(serverName);
            log.info("AOP环绕通知【时间戳为:{}】=========={}#{}方法获取到的serverName为：【{}】", currentTimeMillis, className, methodName, serverName);

        }
        Object result = null;
        try {
            //获取参数
            Object[] args = joinPoint.getArgs();
            if (args == null || args.length == 0) {
                result = joinPoint.proceed();
            } else {
                result = joinPoint.proceed(args);
            }
        } catch (Throwable e) {
            log.error("AOP环绕通知【时间戳为:{}】=========={}#{}方法执行异常。异常原因为：{}=============>", currentTimeMillis, className, methodName, e);
            throw new IllegalStateException("AOP环绕通知【时间戳为:" + currentTimeMillis + "】==========" + className + "#" + methodName + "方法执行异常=============>");
        } finally {
            log.info("AOP环绕通知【时间戳为:{}】=========={}#{}方法执行结束", currentTimeMillis, className, methodName);
            MqContextHolder.clearServerName();
        }
        return result;
    }


    @Override
    public int getOrder() {
        return 0;
    }


}
